#include "stm32l0xx_hal.h"

static void i2c_sda_input(void)
{
  GPIO_InitTypeDef  GPIO_InitStruct;
  GPIO_InitStruct.Pin        = GPIO_PIN_7;
  GPIO_InitStruct.Speed      = GPIO_SPEED_LOW;
  GPIO_InitStruct.Mode       = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull       = GPIO_PULLUP;
  HAL_GPIO_Init( GPIOB, &GPIO_InitStruct );
}

static void i2c_sda_output(void)
{
  GPIO_InitTypeDef  GPIO_InitStruct;
  GPIO_InitStruct.Pin        = GPIO_PIN_7;
  GPIO_InitStruct.Speed      = GPIO_SPEED_LOW;
  GPIO_InitStruct.Mode       = GPIO_MODE_OUTPUT_PP; 
  HAL_GPIO_Init( GPIOB, &GPIO_InitStruct );
}

static void i2c_start(void)
{
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
  HAL_Delay(1);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
  HAL_Delay(1);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
  HAL_Delay(1);
}

static void i2c_stop(void)
{
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
  HAL_Delay(1);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
  HAL_Delay(1);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
  HAL_Delay(1);
}

static void app_test_write(uint8_t data)
{
  uint8_t i;
  for(i = 0; i < 8; i++)
  {
      if(0x80 & data){
          HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
      }else{
          HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
      }
      HAL_Delay(1);
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
      HAL_Delay(1);
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
      HAL_Delay(1);
      
      data <<= 1;
  }
}

static void app_test_read(uint8_t* data)
{
  uint8_t i,tmp = 0;
  for(i = 0; i < 8; i++)
  {
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
      HAL_Delay(1);
      tmp= (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7));
      *data |= (tmp << (7 - i));
      HAL_Delay(1);
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
      HAL_Delay(1);
  }
}


uint8_t i, addr_w = 0x88, addr_r = 0x89, msb = 0x2C, lsb = 0x10, data, ack = 0;

void app_i2c_test_1(void)
{

  GPIO_InitTypeDef  GPIO_InitStruct;

  /* Enable I2C GPIO clocks */
  __GPIOB_CLK_ENABLE();

  /* I2C_EXPBD SCL and SDA pins configuration -------------------------------------*/
  GPIO_InitStruct.Pin        = GPIO_PIN_6;
  GPIO_InitStruct.Mode       = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed      = GPIO_SPEED_LOW;
  GPIO_InitStruct.Pull       = GPIO_NOPULL;

  HAL_GPIO_Init( GPIOB, &GPIO_InitStruct );
 
  GPIO_InitStruct.Pin        = GPIO_PIN_7;
  GPIO_InitStruct.Mode       = GPIO_MODE_OUTPUT_PP;       
  HAL_GPIO_Init( GPIOB, &GPIO_InitStruct );
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
  
  /*ST*/
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
  HAL_Delay(1);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
  HAL_Delay(1);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
  HAL_Delay(1);
  /*SAD+W*/
  app_test_write(addr_w);
  /*sak*/
  i2c_sda_input();
  HAL_Delay(1);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
  HAL_Delay(1);
  ack = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
  HAL_Delay(1);
  /*MSB*/
  i2c_sda_output();
  HAL_Delay(1);
  app_test_write(msb);
  /*sak*/
  i2c_sda_input();
  HAL_Delay(1);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
  HAL_Delay(1);
  ack = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
  HAL_Delay(1);
  /*LSB*/
  i2c_sda_output();
  HAL_Delay(1);
  app_test_write(lsb);
  /*sak*/
  i2c_sda_input();
  HAL_Delay(1);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
  HAL_Delay(1);
  ack = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
  HAL_Delay(1);
  /*SP*/
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
  HAL_Delay(1);
  /*ST*/
  i2c_sda_output();
  HAL_Delay(1);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
  HAL_Delay(1);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
  HAL_Delay(1);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
  HAL_Delay(1);
  /*SAD+R*/
  i2c_sda_output();
  HAL_Delay(1);
  app_test_write(addr_r);
  HAL_Delay(1);
  /*read data*/
  i2c_sda_input();
  HAL_Delay(1);
  /*sak*/
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
  HAL_Delay(1);
  ack = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7);

  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
  HAL_Delay(1);
  app_test_read(&data);
  HAL_Delay(1);
  
}

void app_i2c_test(void)
{
  uint8_t i, addr_w = 0x32, addr_r = 0x33, data, ack = 0;
  uint8_t id_reg = 0x0f;
  GPIO_InitTypeDef  GPIO_InitStruct;

  /* Enable I2C GPIO clocks */
  __GPIOB_CLK_ENABLE();

  /* I2C_EXPBD SCL and SDA pins configuration -------------------------------------*/
  GPIO_InitStruct.Pin        = GPIO_PIN_6;
  GPIO_InitStruct.Mode       = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed      = GPIO_SPEED_LOW;
  GPIO_InitStruct.Pull       = GPIO_NOPULL;

  HAL_GPIO_Init( GPIOB, &GPIO_InitStruct );
 
  GPIO_InitStruct.Pin        = GPIO_PIN_7;
  GPIO_InitStruct.Mode       = GPIO_MODE_OUTPUT_PP;       
  HAL_GPIO_Init( GPIOB, &GPIO_InitStruct );
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
  
  /*ST*/
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
  HAL_Delay(1);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
  HAL_Delay(1);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
  HAL_Delay(1);
  /*SAD+W*/
  app_test_write(addr_w);
  /*sak*/
  i2c_sda_input();
  HAL_Delay(1);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
  HAL_Delay(1);
  ack = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
  HAL_Delay(1);
  /*SUB*/
  i2c_sda_output();
  HAL_Delay(1);
  app_test_write(id_reg);
  /*sak*/
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
  HAL_Delay(1);
  ack = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
  HAL_Delay(1);
  /*SR*/
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
  HAL_Delay(1);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
  HAL_Delay(1);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
  HAL_Delay(1);
  /*SAD+R*/
  app_test_write(addr_r);
  /*read data*/
  i2c_sda_input();
  /*sak*/
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
  HAL_Delay(1);
  ack = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7);

  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
  HAL_Delay(1);
  app_test_read(&data);
  HAL_Delay(1);
  /*sak*/
  /*SP*/
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
  
}